package MyConnectionPool;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class MyConPool implements ConPool {

    /*单例设计模式开始*/
    private MyConPool() {
        idle = new LinkedBlockingQueue<>();//空闲连接
        busy = new LinkedBlockingQueue<>();//繁忙连接
        init();
    }

    //单例的最佳实践：枚举实现单例
    public enum PoolEnum {
        INSTANCE;
        private ConPool pool = null;

        PoolEnum() {
            pool = new MyConPool();
        }

        public ConPool getPoolInstance() {
            return pool;
        }
    }
    /*单例设计模式结束*/

    //当状态是原子就不会有安全问题，有中间态就不安全
    // 静态资源--cdn 静态化，动静态分离
    //读请求--缓存
    //写请求：集群/分布式/微服务

    private final int INIT_SIZE = 10;//初始连接数为10个
    private AtomicInteger maxSize = new AtomicInteger(20);//最大连接数
    private AtomicInteger activeSize = new AtomicInteger(0);//当前已有的连接数
    private LinkedBlockingQueue<Connection> idle;//空闲队列
    private LinkedBlockingQueue<Connection> busy;//繁忙队列


    public void init() {
        //初始化10个连接
        Connection conn =null;
        for (int i = 0; i < INIT_SIZE; i++) {
            try {
                conn = MysqlUtils.createConn();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            Objects.requireNonNull(conn,"连接不能为空"+getClass().getName());
            idle.offer(conn);
        }
    }

    @Override
    public void destory() {

    }

    @Override
    public Connection getConn() {
        //idle 有值 直接取
        Connection conn = idle.poll();
        if (null != conn) {
            busy.offer(conn);
            return conn;
        }
        //idle 无值，若池子未满，创建
        //原子的双重判断，规避锁
        if (activeSize.get() < maxSize.get()) {//性能开销不一样
            if (activeSize.incrementAndGet() < this.maxSize.get()) {
                try {
                    conn = MysqlUtils.createConn();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                busy.offer(conn);
                return conn;
            }
        }
        //池满，全繁忙，等待返回
        try {
            String name = Thread.currentThread().getName();
            System.out.println(name);
            //10秒钟没有拿到
            conn = idle.poll(10000, TimeUnit.MILLISECONDS);
            Objects.requireNonNull(conn, name + "连接超时，抛出空指针异常，正常现象");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void release(Connection conn) {
        busy.remove(conn);
        idle.offer(conn);
    }
}
